

#include "sfc/io.h"
#include "sfc/serde.h"
#include "sfc/test.h"

namespace sfc::serde {

SFC_TEST(ser_bool) {
  {
    auto node = serde::serialize(true);
    test::assert_eq(node.as_bool(), Option{true});
  }

  {
    auto node = serde::serialize(false);
    test::assert_eq(node.as_bool(), Option{false});
  }
}

SFC_TEST(ser_int) {
  {
    auto node = serde::serialize(-123);
    test::assert_eq(node.as_int(), Option{-123});
  }

  {
    auto node = serde::serialize(12345678910U);
    test::assert_eq(node.as_int(), Option{12345678910});
  }
}

SFC_TEST(ser_flt) {
  {
    auto node = serde::serialize(-1.23);
    test::assert_flt_eq(node.as_flt().unwrap(), -1.23);
  }

  {
    auto node = serde::serialize(+1.23f);
    test::assert_flt_eq(node.as_flt().unwrap(), +1.23f);
  }
}

SFC_TEST(ser_str) {
  {
    auto node = serde::serialize("");
    test::assert_eq(node.as_str(), Option{""});
  }

  {
    auto node = serde::serialize("abc");
    test::assert_eq(node.as_str(), Option{"abc"});
  }
}

SFC_TEST(ser_array) {
  {
    const int v[] = {1, 2, 3};
    auto node = serde::serialize(v);
    test::assert_true(node.as_list());

    test::assert_eq(node.len(), 3U);

    test::assert_eq(node[0].as_int(), Option{1});
    test::assert_eq(node[1].as_int(), Option{2});
    test::assert_eq(node[2].as_int(), Option{3});
  }
}

SFC_TEST(ser_vector) {
  {
    auto v = Vec<int>{};
    v.push(1);
    v.push(2);
    v.push(3);

    auto node = serde::serialize(v);
    test::assert_true(node.as_list());

    test::assert_eq(node.len(), 3U);

    test::assert_eq(node[0].as_int(), Option{1});
    test::assert_eq(node[1].as_int(), Option{2});
    test::assert_eq(node[2].as_int(), Option{3});
  }
}

SFC_TEST(ser_dict) {
  {
    auto v = VecMap<String, int>{};
    v.insert(String::from("a"), 1);
    v.insert(String::from("b"), 2);

    auto node = serde::serialize(v);
    test::assert_true(node.as_dict());
    test::assert_eq(node.len(), 2U);
  }
}

namespace {
enum class TestEnum1 { A, B, C };
SFC_ENUM(TestEnum1, A, B, C);
}  // namespace

SFC_TEST(ser_enum) {
  const auto node = serialize(TestEnum1::B);
  test::assert_eq(node.as_str(), Option{"B"});
}

namespace {
struct TestStruct {
  int a;
  float b[2];
};
SFC_STRUCT(TestStruct, a, b);
}  // namespace

SFC_TEST(ser_struct) {
  const auto val = TestStruct{
      1,
      {2, 3},
  };
  const auto node = serialize(val);
  test::assert_true(node.as_dict());
}

}  // namespace sfc::serde
